Welcome! While we're waiting:
- Please download the workshop files from:
- Download zip folder, unzip, and open the file titled: leaflet-webmaps-in-R.html
3/8/2018
Welcome! While we're waiting:
Basic Maps
Data Maps
Doing More
This workshop/tutorial will walk you through the basics of using the Leaflet mapping package in R. You can follow along in any of the three formats:
To begin, lets set up our packages and environment.
Load the packages we will use today
library(leaflet) library(RColorBrewer) library(sp) library(rgdal) library(htmlwidgets) library(magrittr) # or dplyr
Install any packages that you do not have on your computer
# install.packages("leaflet")
# install.packages("RColorBrewer")
# install.packages("sp")
# install.packages("rgdal")
# install.packages("htmlwidgets")
# install.packages("magrittr") # or dplyr
Leaflet is a lightweight, yet powerful javascript library for creating interactive web maps.

Leaflet maps are a combination of HTML and Javascript code that is meant to be rendered in a web browser.
We can use the R leaflet package to create Leaflet maps in R
map1 <- leaflet() # Initialize the map object map1 <- addTiles(map1) # Add basemap tiles map1 # Display the map
Note, we are adding to an exisiting map1
map1 <- setView(map1, lat=37.870044, lng=-122.258169, zoom = 15) map1
Requires dplyr or magrittr package to be loaded
map2 <- leaflet() %>%
addTiles() %>%
setView(lat=37.870044, lng=-122.258169, zoom = 15)
map2
map2
Regular
map1 <- leaflet() map1 <- addTiles(map1) map1 <- setView(map1, lat=37.870044, lng=-122.258169, zoom = 15) map1
Piping
map2 <- leaflet() %>%
addTiles() %>%
setView(lat=37.870044, lng=-122.258169, zoom = 18)
map2
mapRerun the piping code changing the zoom level
By Default, Leaflet uses the OpenStreetMap basemap.
There are a number of other freely availble basemaps that you can also use.
You can customize the basemap with the addProviderTiles function
Check out the documentation
?addProviderTiles
And open the web page of available basemaps
Here's the syntax - instead of using addTiles you use addProviderTiles
map2 <- leaflet() %>%
addProviderTiles("Esri.WorldStreetMap") %>%
setView(lat=37.870044, lng=-122.258169, zoom = 12)
map2
Source: https://mapwarper.net/maps/25477#Preview_tab
mapurl <- "https://mapwarper.net/maps/tile/25477/{z}/{x}/{y}.png"
map2 <- leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
addTiles(mapurl) %>% # custom
setView(lat=37.870044, lng=-122.258169, zoom = 13)
addTiles and addProviderTilesmap2
Note that the setView function is commented out.
setView.map3 <- leaflet() %>% addTiles() %>% # Add default OpenStreetMap map tiles #setView(lat=37.870044, lng=-122.258169, zoom = 17) %>% addMarkers(lat=37.870044, lng=-122.258169, popup="Go Bears!")
map3 # Display the map - Click on the marker
San Francisco Open Data Portal
This data set includes the Office of the Assessor-Recorder’s secured property tax roll spanning from 2015.
We are using this as a proxy for home values.
We are working with a simplified sample of the full data set.
Set your working directory first to the folder where you downloaded the workshop files!
sfhomes <- read.csv('data/sfhomes15.csv', stringsAsFactors = FALSE)
str(sfhomes)
## 'data.frame': 680 obs. of 11 variables: ## $ SalesDate : chr "2015-08-21" "2015-08-13" "2015-12-29" "2015-07-06" ... ## $ Address : chr "0000 2760 19TH AV0015" "0000 0560AMISSOURI ST0000" "0000 0718 LONG BRIDGE ST1202" "0000 0899 VALENCIA ST0202" ... ## $ YrBuilt : int 1979 2003 2016 2015 1961 1900 2015 NA 1947 1907 ... ## $ NumBeds : int 2 2 2 3 3 2 2 0 0 3 ... ## $ NumBaths : int 2 2 2 3 3 2 2 0 0 3 ... ## $ NumUnits : int 1 1 1 1 1 1 1 1 1 1 ... ## $ AreaSqFt : int 1595 1191 1346 1266 1840 1256 1520 536 950 1837 ... ## $ Neighborhood: chr "Twin Peaks" "Potrero Hill" "Mission Bay" "Mission" ... ## $ Value : int 865000 1402560 2260993 1700000 2309692 2700564 1925000 583768 944180 1750001 ... ## $ lat : num 37.7 37.8 37.8 37.8 37.8 ... ## $ lon : num -122 -122 -122 -122 -122 ...
head(sfhomes)
## SalesDate Address YrBuilt NumBeds NumBaths ## 1 2015-08-21 0000 2760 19TH AV0015 1979 2 2 ## 2 2015-08-13 0000 0560AMISSOURI ST0000 2003 2 2 ## 3 2015-12-29 0000 0718 LONG BRIDGE ST1202 2016 2 2 ## 4 2015-07-06 0000 0899 VALENCIA ST0202 2015 3 3 ## 5 2015-06-12 0000 1333 JONES ST0808 1961 3 3 ## 6 2015-04-14 0000 1904 BAKER ST0000 1900 2 2 ## NumUnits AreaSqFt Neighborhood Value lat lon ## 1 1 1595 Twin Peaks 865000 37.73601 -122.4741 ## 2 1 1191 Potrero Hill 1402560 37.75920 -122.3965 ## 3 1 1346 Mission Bay 2260993 37.77181 -122.3942 ## 4 1 1266 Mission 1700000 37.75876 -122.4210 ## 5 1 1840 Nob Hill 2309692 37.79362 -122.4149 ## 6 1 1256 Pacific Heights 2700564 37.78881 -122.4437
map4 <- leaflet() %>%
addTiles() %>%
addMarkers(lat=sfhomes$lat, lng=sfhomes$lon,
popup= paste("Address:", sfhomes$Address,
"<br>",
"Property Value: ", sfhomes$Value))
map4 # Thoughts?
We can save the popup code as a string and re-use it instead of typing it over and over again.
popup_content <- paste("<b>Address:</b>", sfhomes$Address,"<br>",
"<b>Property Value</b>: ", sfhomes$Value, "<br>",
"<b>Neighborhood:</b> ", sfhomes$Neighborhood, "<br>",
"<b>Num Bedrooms: </b>", sfhomes$NumBeds, "<br>",
"<b>Num Bathrooms:</b>", sfhomes$NumBaths
)
We can also use shorter syntax
map4 <- leaflet(sfhomes) %>% addTiles() %>% addMarkers(~lon, ~lat, popup = popup_content)
leaflet we can reference column values directly.tilde operator to map the data to the addMarkers function.lng and lat are not named (e.g. lng=lon) then they must be in the expected order (lng, lat).map4 # - check out the popups now
The map is too crowded with Markers.
Read the addMarker documentation for options to address this.
addMarkers(map, lng = NULL, lat = NULL, layerId = NULL,
group = NULL, icon = NULL, popup = NULL,
options = markerOptions(),
clusterOptions = NULL, clusterId = NULL,
data = getMapData(map))
map4 <- leaflet(sfhomes) %>%
addTiles() %>%
addMarkers(~lon, ~lat, popup= popup_content,
clusterOptions = 1)
map4 # Explore the Map - hover over a cluster marker, zoom in.
addCirleMarker
map4 <- leaflet(sfhomes) %>% addTiles() %>% addCircleMarkers(~lon, ~lat, popup = popup_content)
addCirleMarker
map4
addCircleMarkers(map, lng = NULL, lat = NULL, radius = 10,
layerId = NULL, group = NULL, stroke = TRUE, color = "#03F",
weight = 5, opacity = 0.5,
fill = TRUE, fillColor = color, ....)
Change color, radius and stroke weight of circle markers
map4 <- leaflet(sfhomes) %>%
addTiles() %>%
addCircleMarkers(~lon, ~lat, popup = popup_content,
color="white", radius=6, weight=2, # stroke
fillColor="red",fillOpacity = 0.75 # fill
)
colors() to see a list of all R named colors.map4
Art + Science
Finding the right symbology - size, color, shape, etc
and mapping it to your data
Often requires a classification scheme
We can symbolize the size of points by data values by making the radius of the circle a function of a data value.
map4 <- leaflet(sfhomes) %>%
addProviderTiles("CartoDB.Positron") %>%
addCircleMarkers(~lon, ~lat, popup=popup_content,
fillColor= NA, color="Red", weight=1, fillOpacity = 0,
radius= ~NumBeds+2
)
map4
Circles and Circle Markers look quite similar.
Circle radii are specified in meters while Circle Markers are specified in pixels.
map4 <- leaflet(sfhomes) %>%
addProviderTiles("CartoDB.Positron") %>%
addCircles(~lon, ~lat, popup=popup_content,
fillColor= NA, color="Red",
weight=1, fillOpacity = 0,
radius= ~NumBeds*10
)
map4
The RColorBrewer package is widely used to create color palettes for maps.
Contrasting colors for categorical data
display.brewer.all(type="qual")
display.brewer.pal(7, "Set3" ) # Try a different number of colors
For highlighting trends in numerical data
display.brewer.all(type="seq")
For highlighting the outliers
display.brewer.all(type="div")
colorFactor maps categorical data to colors
colorFactor(palette, domain, levels = NULL, ordered = FALSE, na.color = "#808080", alpha = FALSE, reverse = FALSE)
colorNumeric applies a simple linear mapping of numeric data to color palette
colorNumeric(palette, domain, na.color = "#808080", alpha = FALSE, reverse = FALSE)
colorQuantile assigns colors to numeric data binned by quantile
colorQuantile(palette, domain, n = 4, probs = seq(0, 1, length.out = n + 1), na.color = "#808080", alpha = FALSE, reverse = FALSE)
colorBin also assigns colors to binned numeric data, but allows for customization
colorBin(palette, domain, bins = 7, pretty = TRUE,
na.color = "#808080", alpha = FALSE, reverse = FALSE)
colorFactor functiondisplay.brewer.all(type="qual")
colorfactor takes as input a color palette and a data object (domain) that contains the full range of possible values to be mapped.
colorfactor returns a function specific to that domain that can be used to output a range of color values.
# Create a qualitative color palette
myColors <- colorFactor("Paired", sfhomes$Neighborhood)
the_color_values <- myColors(sfhomes$Neighborhood) length(the_color_values)
## [1] 680
length(the_color_values) == length(sfhomes$Neighborhood)
## [1] TRUE
unique(the_color_values)
## [1] "#B15928" "#C4AAD2" "#E83F26" "#F57166" "#FBAE63" "#F6905B" "#3EA433" ## [8] "#BFA19E" "#EDD279" "#4F8EC1" "#9BD277" "#FF9939" "#A6CEE3" "#7E54A6" ## [15] "#79A6A3" "#C3A176"
Using a color palette
map4 <- leaflet(sfhomes) %>%
addProviderTiles("CartoDB.Positron") %>%
addCircleMarkers(~lon, ~lat,
popup= popup_content,
fillColor= ~myColors(Neighborhood),
radius=6, color=NA, weight=2, fillOpacity = 1
)
map4 # what neighborhood had the most sales?
map4 <- leaflet(sfhomes) %>%
addProviderTiles("CartoDB.Positron") %>%
addCircleMarkers(~lon, ~lat, popup=popup_content,
fillColor= ~myColors(Neighborhood),
radius=6, color=NA, weight=2,fillOpacity = 1
) %>%
addLegend(title = "Neighborhood", pal = myColors,
values = ~Neighborhood, opacity = 1,
position="bottomleft")
map4
For simple linear scaling of colors to values use colorNumeric
#display.brewer.all(type="seq")
numColors <- colorNumeric("Reds", sfhomes$Value)
map4 <- leaflet(sfhomes) %>%
addProviderTiles("CartoDB.Positron") %>%
addCircleMarkers(~lon, ~lat, popup=popup_content,
fillColor= ~numColors(Value),
radius=6, color="grey", weight=1, fillOpacity = 1
) %>%
addLegend(title = "Property Values", pal = numColors,
values = ~Value, opacity = 1,
position="bottomleft")
map4
You can use colorQuantile to create a color palette based on quantiles
?colorQuantile
Default is 4 bins, but you can set n manually (3 to 7)
#display.brewer.all(type="div")
quantColors <- colorQuantile("Reds", sfhomes$Value, n=5)
map4 <- leaflet(sfhomes) %>%
addProviderTiles("CartoDB.Positron") %>%
addCircleMarkers(~lon, ~lat, popup=popup_content,
fillColor= ~quantColors(Value),
radius=6, color="grey", weight=1,fillOpacity = 1
)
map4
map4 %>% addLegend(title = "Value", pal = quantColors,
values = ~Value, opacity = 1,
position="bottomleft")
map5 <-map4 %>% addLegend(pal = quantColors, values = ~Value,
title = "Property Value, 2015",
position="bottomleft",
opacity=1,
labFormat = function(type, cuts, p) {
n = length(cuts)
cuts = paste0("$", format(cuts[-n], big.mark=","),
" - ", "$",format(cuts[-1], big.mark=","))
}
)
map5
What's happening here?
sfhomes_low2high <- sfhomes[order(sfhomes$Value, decreasing = FALSE),]
map4 <- leaflet(sfhomes_low2high) %>%
addProviderTiles("CartoDB.Positron") %>%
addCircleMarkers(~lon, ~lat, popup=popup_content,
fillColor= ~quantColors(Value),
radius=6, color="grey", weight=1,fillOpacity = 1
)
Does the output map look different from previous map?
map4
Basic Maps
addMarkers - Simple Marker MapsaddCircleMarkers - Circle Marker MapsData Maps
addCircles Proportional symbol mapscolorFactor - Category MapscolorNumeric - Proportional color mapscolorQuantile - Graduated color mapsWe have been working with geographic data in data frames
The coordinates are longitude and latitude
Next up, more complex spatial objects
We can use the sp and `rgdal libaries to import, manipulate and map more complex spatial objects.
sp - R classes and methods for spatial data
rgdal - Functions for importing and transforming spatial data
Let's use these to import data in ESRI Shapefiles
Read in the data
sf_md_hhi <- readOGR(dsn="data",layer="sf_medhhincome_acs5y_16")
## OGR data source with driver: ESRI Shapefile ## Source: "data", layer: "sf_medhhincome_acs5y_16" ## with 196 features ## It has 5 fields
Explore the data
class(sf_md_hhi)
## [1] "SpatialPolygonsDataFrame" ## attr(,"package") ## [1] "sp"
head(sf_md_hhi)
## An object of class "SpatialPolygonsDataFrame" ## Slot "data": ## GEOID NAME ## 0 06075010700 Census Tract 107, San Francisco County, California ## 1 06075011200 Census Tract 112, San Francisco County, California ## 2 06075011901 Census Tract 119.01, San Francisco County, California ## 3 06075012201 Census Tract 122.01, San Francisco County, California ## 4 06075013500 Census Tract 135, San Francisco County, California ## 5 06075015200 Census Tract 152, San Francisco County, California ## variable estimate moe ## 0 B19013_001 22425 2716 ## 1 B19013_001 100139 16777 ## 2 B19013_001 72364 17240 ## 3 B19013_001 43698 12316 ## 4 B19013_001 120714 15421 ## 5 B19013_001 89440 18460 ## ## Slot "polygons": ## [[1]] ## An object of class "Polygons" ## Slot "Polygons": ## [[1]] ## An object of class "Polygon" ## Slot "labpt": ## [1] -122.41005 37.79851 ## ## Slot "area": ## [1] 1.873656e-05 ## ## Slot "hole": ## [1] FALSE ## ## Slot "ringDir": ## [1] 1 ## ## Slot "coords": ## [,1] [,2] ## [1,] -122.4129 37.80218 ## [2,] -122.4114 37.80112 ## [3,] -122.4090 37.79949 ## [4,] -122.4079 37.79870 ## [5,] -122.4071 37.79815 ## [6,] -122.4067 37.79787 ## [7,] -122.4055 37.79706 ## [8,] -122.4084 37.79670 ## [9,] -122.4117 37.79629 ## [10,] -122.4119 37.79724 ## [11,] -122.4123 37.79910 ## [12,] -122.4125 37.80003 ## [13,] -122.4128 37.80189 ## [14,] -122.4129 37.80218 ## ## ## ## Slot "plotOrder": ## [1] 1 ## ## Slot "labpt": ## [1] -122.41005 37.79851 ## ## Slot "ID": ## [1] "0" ## ## Slot "area": ## [1] 1.873656e-05 ## ## ## [[2]] ## An object of class "Polygons" ## Slot "Polygons": ## [[1]] ## An object of class "Polygon" ## Slot "labpt": ## [1] -122.41273 37.79297 ## ## Slot "area": ## [1] 1.813447e-05 ## ## Slot "hole": ## [1] FALSE ## ## Slot "ringDir": ## [1] 1 ## ## Slot "coords": ## [,1] [,2] ## [1,] -122.4163 37.79389 ## [2,] -122.4152 37.79403 ## [3,] -122.4114 37.79453 ## [4,] -122.4097 37.79474 ## [5,] -122.4095 37.79385 ## [6,] -122.4092 37.79204 ## [7,] -122.4125 37.79163 ## [8,] -122.4158 37.79121 ## [9,] -122.4159 37.79213 ## [10,] -122.4161 37.79301 ## [11,] -122.4163 37.79389 ## ## ## ## Slot "plotOrder": ## [1] 1 ## ## Slot "labpt": ## [1] -122.41273 37.79297 ## ## Slot "ID": ## [1] "1" ## ## Slot "area": ## [1] 1.813447e-05 ## ## ## [[3]] ## An object of class "Polygons" ## Slot "Polygons": ## [[1]] ## An object of class "Polygon" ## Slot "labpt": ## [1] -122.41391 37.79047 ## ## Slot "area": ## [1] 6.371875e-06 ## ## Slot "hole": ## [1] FALSE ## ## Slot "ringDir": ## [1] 1 ## ## Slot "coords": ## [,1] [,2] ## [1,] -122.4158 37.79121 ## [2,] -122.4125 37.79163 ## [3,] -122.4123 37.79067 ## [4,] -122.4121 37.78974 ## [5,] -122.4154 37.78932 ## [6,] -122.4156 37.79025 ## [7,] -122.4158 37.79121 ## ## ## ## Slot "plotOrder": ## [1] 1 ## ## Slot "labpt": ## [1] -122.41391 37.79047 ## ## Slot "ID": ## [1] "2" ## ## Slot "area": ## [1] 6.371875e-06 ## ## ## [[4]] ## An object of class "Polygons" ## Slot "Polygons": ## [[1]] ## An object of class "Polygon" ## Slot "labpt": ## [1] -122.41635 37.78585 ## ## Slot "area": ## [1] 9.413017e-06 ## ## Slot "hole": ## [1] FALSE ## ## Slot "ringDir": ## [1] 1 ## ## Slot "coords": ## [,1] [,2] ## [1,] -122.4183 37.78704 ## [2,] -122.4150 37.78745 ## [3,] -122.4146 37.78558 ## [4,] -122.4144 37.78466 ## [5,] -122.4161 37.78445 ## [6,] -122.4177 37.78424 ## [7,] -122.4179 37.78517 ## [8,] -122.4183 37.78704 ## ## ## ## Slot "plotOrder": ## [1] 1 ## ## Slot "labpt": ## [1] -122.41635 37.78585 ## ## Slot "ID": ## [1] "3" ## ## Slot "area": ## [1] 9.413017e-06 ## ## ## [[5]] ## An object of class "Polygons" ## Slot "Polygons": ## [[1]] ## An object of class "Polygon" ## Slot "labpt": ## [1] -122.4326 37.7909 ## ## Slot "area": ## [1] 2.405882e-05 ## ## Slot "hole": ## [1] FALSE ## ## Slot "ringDir": ## [1] 1 ## ## Slot "coords": ## [,1] [,2] ## [1,] -122.4362 37.79226 ## [2,] -122.4346 37.79247 ## [3,] -122.4296 37.79310 ## [4,] -122.4293 37.79134 ## [5,] -122.4289 37.78953 ## [6,] -122.4338 37.78891 ## [7,] -122.4355 37.78870 ## [8,] -122.4358 37.79050 ## [9,] -122.4362 37.79226 ## ## ## ## Slot "plotOrder": ## [1] 1 ## ## Slot "labpt": ## [1] -122.4326 37.7909 ## ## Slot "ID": ## [1] "4" ## ## Slot "area": ## [1] 2.405882e-05 ## ## ## [[6]] ## An object of class "Polygons" ## Slot "Polygons": ## [[1]] ## An object of class "Polygon" ## Slot "labpt": ## [1] -122.43027 37.78791 ## ## Slot "area": ## [1] 2.856017e-05 ## ## Slot "hole": ## [1] FALSE ## ## Slot "ringDir": ## [1] 1 ## ## Slot "coords": ## [,1] [,2] ## [1,] -122.4355 37.78870 ## [2,] -122.4338 37.78891 ## [3,] -122.4289 37.78953 ## [4,] -122.4256 37.78995 ## [5,] -122.4250 37.78713 ## [6,] -122.4283 37.78671 ## [7,] -122.4316 37.78629 ## [8,] -122.4349 37.78588 ## [9,] -122.4355 37.78870 ## ## ## ## Slot "plotOrder": ## [1] 1 ## ## Slot "labpt": ## [1] -122.43027 37.78791 ## ## Slot "ID": ## [1] "5" ## ## Slot "area": ## [1] 2.856017e-05 ## ## ## ## Slot "plotOrder": ## [1] 6 5 1 2 4 3 ## ## Slot "bbox": ## min max ## x -122.43620 -122.40551 ## y 37.78424 37.80218 ## ## Slot "proj4string": ## CRS arguments: ## +proj=longlat +datum=NAD83 +no_defs +ellps=GRS80 +towgs84=0,0,0
Leaflet understands sp objects!!!
map6 <- leaflet() %>% addTiles() %>% addPolygons(data=sf_md_hhi)
map6
?addPolygons
addPolygons(map, lng = NULL, lat = NULL, layerId = NULL, group = NULL,
stroke = TRUE, color = "#03F", weight = 5, opacity = 0.5,
fill = TRUE, fillColor = color, fillOpacity = 0.2,
dashArray = NULL, smoothFactor = 1, noClip = FALSE,
popup = NULL, popupOptions = NULL, label = NULL,
labelOptions = NULL, options = pathOptions(),
highlightOptions = NULL, data = getMapData(map))
map6 <- leaflet() %>%
setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data=sf_md_hhi, color="grey", weight=1,
fillColor="Orange", fillOpacity = 0.25)
map6
Color regions based on data values.
The data values are classified into bins.
Each bin gets a unique color from a color palette.
Median Household Income is in the estimate column
Recipe:
estimate##display.brewer.all(type="seq")
quantColors <- colorQuantile("YlOrRd", sf_md_hhi$estimate, n=5)
map6 <- leaflet() %>%
setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data=sf_md_hhi, color="white", weight=1, opacity=0.5,
fillColor=~quantColors(estimate), fillOpacity = 0.65,
popup = paste0("$",sf_md_hhi$estimate))
map6
map6 <- map6 %>% addLegend(pal = quantColors,
values = sf_md_hhi$estimate,
title = "Median HH Income",
position="bottomleft",
opacity=1,
labFormat = function(type, cuts, p) {
n = length(cuts)
cuts = paste0("$", format(cuts[-n], big.mark=","),
" - ", "$",format(cuts[-1], big.mark=","))
}
)
map6
You can add multiple data layers to a leaflet map.
Let's add the assessed housing value points and see if we can find some cheaper houses in High Income census tracts.
cheap <- sfhomes[sfhomes$Value < 1000000,]
map7 <- leaflet() %>%
setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data=sf_md_hhi, color="white", weight=1, opacity=0.5,
fillColor=~quantColors(estimate), fillOpacity = 0.65,
popup = paste0("$",sf_md_hhi$estimate)) %>%
addCircleMarkers(data=cheap, popup=paste0("$",cheap$Value),
color="black",weight=1, radius=6,
fillColor="white", fillOpacity = 0.75)
map7
To add 'controls' to our map, we use the function addLayersControl().
We assign a group to each basemap and layer (polygon, marker, line, etc).
Then layer switcher allows us to toggle between different basemaps and turn on/off each of the layers.
?addLayersControl
map8 <- leaflet() %>%
setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(data=sf_md_hhi, color="white", weight=1, opacity=0.5,
fillColor=~quantColors(estimate), fillOpacity = 0.65,
popup = paste0("$",sf_md_hhi$estimate),
group="Median HH Income"
) %>%
addCircleMarkers(data=cheap, popup=paste0("$",cheap$Value),
color="black",weight=1, radius=6,
fillColor="white", fillOpacity = 0.75,
group="Property Values"
) %>%
addLayersControl(
overlayGroups = c("Property Values","Median HH Income"),
options = layersControlOptions(collapsed = FALSE)
)
map8
map8 <- leaflet() %>%
setView(lng=-122.448889, lat=37.764645, zoom=12) %>%
addProviderTiles("CartoDB.Positron", group="Simple") %>%
addProviderTiles("Esri.WorldStreetMap", group="Streets") %>%
addPolygons(data=sf_md_hhi, color="white", weight=1, opacity=0.5,
fillColor=~quantColors(estimate), fillOpacity = 0.65,
popup = paste0("$",sf_md_hhi$estimate),
group="Median HH Income"
) %>%
addCircleMarkers(data=cheap, popup=paste0("$",cheap$Value),
color="black",weight=1, radius=6,
fillColor="white", fillOpacity = 0.75,
group="Property Values"
) %>%
addLayersControl(
baseGroups = c("Simple", "Streets"),
overlayGroups = c("Property Values","Median HH Income"),
options = layersControlOptions(collapsed = FALSE)
)
map8
Interactive Maps in R - check
Web Maps can be shared if online.
Easy way to go is RPubs
You can share you map online by publishing it to RPubs.
RPubs account to make that work.Enter the code for your map in the console
In the Viewer window, click on the Publish icon.
Another way to share your map is to save it to a file. You can then email it, host it on your own web server or host it on github, etc.
#library(htmlwidgets) saveWidget(map7, file="testmap.html")
Open your file to by double-clicking on it in the Mac Finder or Windows Explorer.
Getting more Practice
tmap
sp objects within Rleaflet for creating Leaflet maps as well as publication ready static map images.mapview
tmap. I haven't checked it out but I keep seeing it so I think it is emerging.leafletPowerful You can customize it to create great interactive maps
Integrates with Shiny, an R web Framework
Demo w/Tutorial at
Mapbox today at the GIF
Georectifiying Historical Maps at DLAB, March 14
To you!
and to Josh Pepper who did an earlier workshop on which these materials are loosely based.